001    package EVolve;
002    
003    import EVolve.*;
004    import EVolve.exceptions.*;
005    import EVolve.data.*;
006    import EVolve.util.*;
007    
008    import java.io.*;
009    import java.util.*;
010    import javax.swing.*;
011    
012    import adaptj.*;
013    import adaptj.util.*;
014    import adaptj.toolkits.*;
015    import adaptj.toolkits.continuous.*;
016    
017    import it.unimi.dsi.fastUtil.*;
018    
019    public class ContinuousDataSource implements DataSource {
020        public static final String DATASOURCE_NAME = "ContinuousDataSource";
021        
022        private BufferedFileReader input;
023        private long mark = 0L;
024        private String currentFileName;
025    
026        private Int2ObjectOpenHashMap metrics;
027        private Int2ObjectOpenHashMap triggers;
028        //private Int2ObjectOpenHashMap metricToTriggers;
029        
030        private int maxMetricID;
031        private int maxTriggerID;
032    
033        // For iterating over all definitions
034        private int currentMetricID;
035        private int currentTriggerID;
036    
037        // double arrays are indexed by metric ID, then trigger ID
038        private long[] eventCounts;
039        private ElementDefinition[] definitions;
040        private List[] fields;
041        private EventBuilder[] builders;
042    
043        private EntityBuilder triggerEntityBuilder;
044        private Int2ObjectOpenHashMap triggerEntities;
045    
046        private LineTokenizer tokenizer;
047    
048        private String[] propertyCount = {"time", "count"};
049        private String[] propertyAmount = {"time", "amount"};
050        private String[] propertyMetric = {"metric"};
051        private String[] propertyTrigger = {"trigger"};
052            
053        public void init() throws EVolveException {
054            String fn = EVolve.Scene.getDataFileName();
055            if (fn == null) {
056                JFileChooser fc = new JFileChooser(EVolve.Scene.getUIManager().getLastDataDir());
057                if (fc.showOpenDialog(EVolve.Scene.getFrame()) == JFileChooser.APPROVE_OPTION) {
058                    try {
059                        File f = fc.getSelectedFile();
060                        input = new BufferedFileReader(f);
061                        fn = f.getName();
062                        EVolve.Scene.setDataFilename(f.getPath());
063                        EVolve.Scene.getUIManager().setLastDataDir(f.getPath());
064                        EVolve.Scene.setDataFilename(null);
065                    } catch (IOException e) {
066                        throw new DataProcessingException("IO exception occurred when access data file.");
067                    }
068                } else {
069                    throw new CancelLoadDataException();
070                }
071            } else {
072                try {
073                    input = new BufferedFileReader(fn);
074                } catch (IOException e) {
075                    throw new DataProcessingException("File loading failed.");
076                }
077            }
078    
079            currentFileName = fn;
080            tokenizer = new LineTokenizer();
081        }
082    
083        public String getName() {
084            return DATASOURCE_NAME;
085        }
086    
087        public String getFileName() {
088            return currentFileName;
089        }
090    
091        public void startBuildDefinition() throws DataProcessingException {
092            String line;
093            maxMetricID = 0;
094            maxTriggerID = 0;
095    
096            metrics = new Int2ObjectOpenHashMap();
097            triggers = new Int2ObjectOpenHashMap();
098            //metricToTriggers = new Int2ObjectOpenHashMap();
099    
100            // Reminder: file format
101            // TRIGGER <id> <trigger description> [INTERVAL]
102            // METRIC <id> <name>                                       
103            // MAP <trigger id> <metric id>+
104            // <trigger id> <metric id> <metric value> [interval counter]
105            try {
106                while ((line = input.readLine()) != null) {
107                    line = line.trim();
108                    if (line.startsWith("#")) {
109                        // This input line is a comment -- Skip it
110                    } else if (line.equals("")) {
111                        // This input line is a blank line -- Skip it
112                    } else if (line.startsWith("TRIGGER")) {
113                        tokenizer.setLine(line);
114                        // Skip "TRIGGER"
115                        tokenizer.getNext();
116    
117                        int triggerIndex = Integer.parseInt(tokenizer.getNext());
118                        String triggerDesc = tokenizer.getRemaining();
119                        boolean interval = false;
120                        if (triggerDesc.endsWith(" INTERVAL")) {
121                            interval = true;
122                            triggerDesc = triggerDesc.substring(0, triggerDesc.length() - 9);
123                        }
124                        triggers.put(triggerIndex, triggerDesc);
125                        if (maxTriggerID < triggerIndex) {
126                            maxTriggerID = triggerIndex;
127                        }
128    
129                        // DEBUG
130                        System.out.println("Trigger: " + triggerIndex + " " + triggerDesc + (interval ? " [INTERVAL]" : ""));
131                    } else if (line.startsWith("METRIC")) {
132                        tokenizer.setLine(line);
133                        // Skip "METRIC"
134                        tokenizer.getNext();
135                        
136                        int metricIndex = Integer.parseInt(tokenizer.getNext());
137                        String metricName = tokenizer.getRemaining();
138                        metrics.put(metricIndex, metricName);
139                        if (maxMetricID < metricIndex) {
140                            maxMetricID = metricIndex;
141                        }
142    
143                        // DEBUG
144                        System.out.println("Metric: " + metricIndex + " " + metricName);
145                    } else if (line.startsWith("MAP")) {
146                        // Ignore at this time
147                        /*
148                        tokenizer.setLine(line);
149                        
150                        // Skip "MAP"
151                        tokenizer.getNext();
152    
153                        int triggerIndex = Integer.parseInt(tokenizer.getNext());
154                        while (tokenizer.hasNext()) {
155                            int metricIndex = Integer.parseInt(tokenizer.getNext());
156                            IntHashSet triggerSet;
157                            if (metricToTriggers.containsKey(metricIndex)) {
158                                triggerSet = (IntHashSet) metricToTriggers.get(metricIndex);
159                            } else {
160                                triggerSet = new IntHashSet("ContinuousDataSource.Metric#" + metricIndex);
161                                metricToTriggers.put(metricIndex, triggerSet);
162                            }
163                            triggerSet.add(triggerIndex);
164                        }
165                        */
166                        // DEBUG
167                        //System.out.println("Map");
168                    } else {
169                        System.out.println("Starting to read events");
170                        break;
171                    }
172                    mark = input.getFilePointer();
173                }
174    
175                eventCounts = new long[maxMetricID + 1];//[maxTriggerID + 1];
176                definitions = new ElementDefinition[maxMetricID + 1];//[maxTriggerID + 1];
177                fields = new List[maxMetricID + 1];//[maxTriggerID + 1];
178                builders = new EventBuilder[maxMetricID + 1];//[maxTriggerID + 1];
179    
180                while (line != null) {
181                    tokenizer.setLine(line);
182                    // Trigger index
183                    //int triggerIndex = Integer.parseInt(tokenizer.getNext());
184    
185                    // Metric index
186                    int metricIndex = Integer.parseInt(tokenizer.getNext());
187    
188                    //eventCounts[metricIndex][triggerIndex] += 1L;
189                    eventCounts[metricIndex] += 1L;
190                    line = input.readLine();
191                }
192            } catch (IOException e) {
193                throw new DataProcessingException("File processing failed.");
194            //} catch (ArrayIndexOutOfBoundsException e) {
195            //    throw new DataProcessingException("File processing failed (invalid file format).");
196            }
197            
198            currentMetricID = 0;
199            //currentTriggerID = 0;
200            System.out.println("Definitions built. Will iterate next");
201            System.out.println("Max Metric ID = " + maxMetricID);
202            System.out.println("Max Trigger ID = " + maxTriggerID);
203        }
204    
205        public ElementDefinition getNextDefinition() throws DataProcessingException {
206            ElementDefinition result = null;
207            
208            if (triggerEntityBuilder == null) {
209                triggerEntityBuilder = new EntityBuilder("Trigger", "Trigger");
210                return triggerEntityBuilder.buildDefinition();
211            }
212    
213            for (int i = currentMetricID; i <= maxMetricID && result == null; i++, currentMetricID++) {
214                if (eventCounts[i] > 0L) {
215                    // Build an event definition for this
216                    String eventName = (String) metrics.get(i); // + " - " + triggers.get(j);
217                    EventBuilder builder = new EventBuilder(eventName, eventName);
218                    List l = new ArrayList();
219                    l.add(builder.buildReferenceDefinition("Trigger", triggerEntityBuilder, propertyTrigger, "Trigger"));
220                    l.add(builder.buildValueDefinition("Occurences", propertyCount, "Occurences"));
221                    l.add(builder.buildValueDefinition("Value", propertyMetric, "Metric Value"));
222                    result = builder.buildDefinition();
223    
224                    fields[i] = l;
225                    definitions[i] = result;
226                    builders[i] = builder;
227                }
228            }
229    
230            /*
231            for (int i = currentMetricID; i <= maxMetricID; i++, currentMetricID++) {
232                for (int j = currentTriggerID; j <= maxTriggerID; j++, currentTriggerID++) {
233                    if (eventCounts[i][j] > 0L) {
234                        // Build an event definition for this
235                        String eventName = (String) metrics.get(i); // + " - " + triggers.get(j);
236                        EventBuilder builder = new EventBuilder(eventName, eventName);
237                        List l = new ArrayList();
238                        l.add(builder.buildValueDefinition("Value", propertyMetric, "Metric Value"));
239                        l.add(builder.buildValueDefinition("Occurences", propertyCount, "Occurences"));
240                        l.add(builder.buildReferenceDefinition("Trigger", triggerEntityBuilder, propertyTrigger, "Trigger"));
241                        result = builder.buildDefinition();
242    
243                        fields[i][j] = l;
244                        definitions[i][j] = result;
245                        builders[i][j] = builder;
246    
247                        System.out.println("Looked at (" + i + ", " + j + ") --> " + eventName);
248    
249                        if (result != null) {
250                            if (++currentTriggerID > maxTriggerID) {
251                                currentTriggerID = 0;
252                                currentMetricID++;
253                            }
254    
255                            return result;
256                        }
257                    }
258                }
259            }
260            */
261    
262            
263            
264            return result;
265        }
266    
267        public long getNumberOfEvents(String definitionName) {
268            for (int i = 0; i < maxMetricID; i++) {
269                ElementDefinition def = definitions[i];
270                if (def != null && definitionName.equals(def.getName())) {
271                    return eventCounts[i];
272                }
273            }
274            return 0L;
275        }
276    
277        public long getTotalNumberOfEvents() {
278            long result = 0L;
279            for (int i = 0; i < maxMetricID; i++) {
280                result += eventCounts[i];
281            }
282    
283            return result;
284        }
285        
286        public void startBuildEntity() throws DataProcessingException {
287            currentTriggerID = 0;
288            triggerEntities = new Int2ObjectOpenHashMap();
289        }
290    
291        public Entity getNextEntity() throws DataProcessingException {
292            if (currentTriggerID <= maxTriggerID) {
293                triggerEntityBuilder.newEntity((String) triggers.get(currentTriggerID));
294                Entity triggerEntity = triggerEntityBuilder.buildEntity();
295                triggerEntities.put(currentTriggerID, triggerEntity);
296                currentTriggerID++;
297                return triggerEntity;
298            }
299    
300            return null;
301        }
302    
303        public void startBuildEvent() throws DataProcessingException {
304            try {
305                input.seek(mark);
306            } catch (IOException e) {
307                throw new DataProcessingException("File processing failed");
308            }
309        }
310    
311        public Event getNextEvent() throws DataProcessingException {
312            Event result = null;
313            try {
314                String line;
315                while ((line = input.readLine()) != null) {
316                    int currentField = 0;
317                    tokenizer.setLine(line);
318                    // Trigger index
319                    int triggerIndex = Integer.parseInt(tokenizer.getNext());
320                    // Metric index
321                    int metricIndex = Integer.parseInt(tokenizer.getNext());
322                    // Metric value
323                    double metric = Double.parseDouble(tokenizer.getNext());
324    
325                    System.err.println("Trigger: " + triggerIndex + " Metric: " + metricIndex + " Value: " + metric);
326    
327                    // Interval counter
328                    /*
329                    int intervalCounter = -1;
330                    if (tokenizer.hasNext()) {
331                        intervalCounter = Integer.parseInt(tokenizer.getNext());
332                    }
333                    */
334                    
335                    EventBuilder builder = builders[metricIndex];
336                    List l = fields[metricIndex];
337                    
338                    builder.newEvent();
339                    builder.addValueField((FieldDefinition)l.get(currentField++), (int)(metric * 1000));
340                    builder.addValueField((FieldDefinition)l.get(currentField++), 1);
341                    builder.addReferenceField((FieldDefinition)l.get(currentField++), (Entity)triggerEntities.get(triggerIndex));
342    
343                    return builder.buildEvent();
344                }
345            } catch (IOException e) {
346                throw new DataProcessingException("File processing failed");
347            }
348    
349            return null;
350        }
351    
352    
353        class LineTokenizer {
354            private String line;
355            private int start;
356            private int end;
357            private int len;
358    
359            LineTokenizer() {
360                this(null);
361            }
362    
363            LineTokenizer(String line) {
364                setLine(line);
365            }
366    
367            public void setLine(String line) {
368                this.line = line;
369                if (line != null) {
370                    line = line.trim();
371                    len = line.length();
372                } else {
373                    len = -1;
374                }
375                start = 0;
376                end = 0;
377            }
378    
379            public boolean hasNext() {
380                return end < len;
381            }
382    
383            public String getNext() {
384                if (end < len) {
385                    end = line.indexOf(' ', start);
386                    if (end < 0) {
387                        end = len;
388                    }
389                    
390                    String result = line.substring(start, end);
391                    start = end + 1;
392                    return result;
393                }
394    
395                return null;
396            }
397    
398            public String getRemaining() {
399                if (end < len) {
400                    end = len;
401                    return line.substring(start);
402                }
403    
404                return null;
405            }
406        }
407    }
408